﻿#include "y2yUI.h"

y2yUI::y2yUI(QWidget *parent)
    : QDialog(parent)
    , ui(new Ui::y2yUIClass())
    , isFileKey(false)
    , isAddFile(false)
{
    ui->setupUi(this);

    defaultPushbuttonColor = ui->pushButton_isFileKey->palette().color(QPalette::Window);

    // connect signals and slots
    connect(ui->toolButton_input, SIGNAL(clicked()), this, SLOT(inputFile_button_clicked()));
    connect(ui->toolButton_outPath, SIGNAL(clicked()), this, SLOT(outputPath_button_clicked()));
    connect(ui->pushButton_isFileKey, SIGNAL(clicked()), this, SLOT(pushButton_isFileKey_clicked()));
    connect(ui->toolButton_keyFile, SIGNAL(clicked()), this, SLOT(toolButton_keyFile_clicked()));
    connect(ui->pushButton_add, SIGNAL(clicked()), this, SLOT(pushButton_add_clicked()));
    connect(ui->pushButton_cover, SIGNAL(clicked()), this, SLOT(pushButton_cover_clicked()));
    connect(ui->pushButton_textToFile, SIGNAL(clicked()), this, SLOT(pushButton_textToFile_clicked()));
    connect(ui->pushButton_show, SIGNAL(clicked()), this, SLOT(pushButton_show_clicked()));
    connect(ui->pushButton_showCodec, SIGNAL(clicked()), this, SLOT(pushButton_showCodec_clicked()));
    connect(ui->pushButton_fileToFile, SIGNAL(clicked()), this, SLOT(pushButton_fileToFile_clicked()));
    connect(ui->pushButton_clear, SIGNAL(clicked()), this, SLOT(pushButton_clear_clicked()));

    connect(ui->comboBox_key, &QComboBox::currentIndexChanged, this, &y2yUI::comboBox_key_currentIndexChanged);

    // 隐藏密钥输入框
    ui->lineEdit_keyFile->hide();
    ui->toolButton_keyFile->hide();
    
    // 隐藏密钥长度框
    ui->spinBox_keyLen->hide();
    ui->horizontalLayout_keyLen->setStretch(1, 10);

    // 设置默认输出文件为覆盖模式，按钮设置为粉色
    QPalette palette;
    palette.setColor(QPalette::Button, QColor(255, 192, 203));
    ui->pushButton_cover->setPalette(palette);

    // 初始化 y2yCtx
    init_y2yCtx(&ctx);
}

y2yUI::~y2yUI()
{
    delete ui;
    free_y2yCtx(&ctx);
}

void y2yUI::inputFile_button_clicked()
{
    QFileDialog fileDialog(this);
    fileDialog.setFileMode(QFileDialog::ExistingFile);
    fileDialog.setNameFilter(tr("Input file (*)"));
    if (fileDialog.exec()) {
        QStringList fileNames = fileDialog.selectedFiles();
        ui->lineEdit_input->setText(fileNames[0]);

        // 去除文件名，只保留路径
        QFileInfo fileInfo(fileNames[0]);
        if (ui->lineEdit_outPath->text().isEmpty())
            ui->lineEdit_outPath->setText(fileInfo.path());
    }
}

void y2yUI::outputPath_button_clicked()
{
    QFileDialog fileDialog(this);
    fileDialog.setFileMode(QFileDialog::Directory);
    if (fileDialog.exec()) {
        QStringList fileNames = fileDialog.selectedFiles();
        // 只保留路径
        ui->lineEdit_outPath->setText(fileNames[0]);
    }
}

void y2yUI::pushButton_isFileKey_clicked()
{
    QPalette palette;
    //palette.setColor(QPalette::Button, QColor(255, 192, 203));
    if (isFileKey) {
        // 选中时设置背景为粉色
        isFileKey = false;

        // 未选中时设置背景为默认颜色
        palette.setColor(QPalette::Button, defaultPushbuttonColor);
        ui->pushButton_isFileKey->setPalette(palette);

        // 隐藏密钥输入框
        ui->lineEdit_keyFile->hide();
        ui->toolButton_keyFile->hide();

        // 显示文件输入框
        ui->lineEdit_keyContent->show();
    }
    else {
        isFileKey = true;
        palette.setColor(QPalette::Button, QColor(255, 192, 203));
        ui->pushButton_isFileKey->setPalette(palette);

        // 显示密钥输入框
        ui->lineEdit_keyFile->show();
        ui->toolButton_keyFile->show();

        // 隐藏文件输入框
        ui->lineEdit_keyContent->hide();
    }
}

void y2yUI::toolButton_keyFile_clicked()
{
    QFileDialog fileDialog(this);
    fileDialog.setFileMode(QFileDialog::ExistingFile);
    fileDialog.setNameFilter(tr("Key file (*)"));
    if (fileDialog.exec()) {
        QStringList fileNames = fileDialog.selectedFiles();
        ui->lineEdit_keyFile->setText(fileNames[0]);
    }
}

void y2yUI::comboBox_key_currentIndexChanged()
{
    //QByteArray key_content;
    //if (isFileKey) {
    //    // 打开文件，获取文件密钥长度
    //    QFile file(ui->lineEdit_keyFile->text());
    //    if (!file.open(QIODevice::ReadOnly)) {
    //        QMessageBox::warning(this, tr("Error"), tr("Failed to open key file. Please check the key file "));
    //        return;
    //    }
    //    //key_content = file.readAll();
    //    file.close();
    //}
    //else {
        //// 输入密钥，获取密钥长度
        //key_content = ui->lineEdit_keyContent->text().toUtf8();
    //}

    if (ui->comboBox_key->currentText() == u8"全部") {
        ui->spinBox_keyLen->hide();
        ui->horizontalLayout_keyLen->setStretch(1, 10);
    }
    else
        ui->spinBox_keyLen->show();

    if (isFileKey) {
        // 打开文件，获取文件密钥长度
        QFile file(ui->lineEdit_keyFile->text());
        if (!file.open(QIODevice::ReadOnly)) {
            QMessageBox::warning(this, tr("Error"), tr("Failed to open key file. Please check the key file "));
            return;
        }
        if (ui->spinBox_keyLen->value() == 1)
            ui->spinBox_keyLen->setValue(file.size());
        file.close();
    }
    else {
        if (ui->spinBox_keyLen->value() == 1 || ui->lineEdit_keyContent->text().isEmpty())
            ui->spinBox_keyLen->setValue(ui->lineEdit_keyContent->text().toUtf8().size());
    }
    //ui->horizontalLayout_keyLen->setStretch(1, 1);
    //keyLen = ui->comboBox_key->currentText().toUtf8().size();
}

inline bool y2yUI::check_input_file()
{
    // 检查输入文件是否存在
    if (ui->lineEdit_input->text().isEmpty()) {
        QMessageBox::warning(this, tr("Error"), tr("Please select the input file."));
        return false;
    }
    QFileInfo check_file(ui->lineEdit_input->text());
    if (!check_file.exists()) {
        QMessageBox::warning(this, tr("Error"), tr("Input file does not exist."));
        return false;
    }
    return true;
}

inline bool y2yUI::check_key()
{
    // 检查密钥文件是否存在，或者密钥内容是否为空
    if (isFileKey && ui->lineEdit_keyFile->text().isEmpty()) {
        QMessageBox::warning(this, tr("Error"), tr("Please select the key file."));
        return false;
    }
    else if (!isFileKey && ui->lineEdit_keyContent->text().isEmpty()) {
        QMessageBox::warning(this, tr("Error"), tr("Please input the key content."));
        return false;
    }
    if (isFileKey) {
        QFileInfo check_file(ui->lineEdit_keyFile->text());
        if (!check_file.exists()) {
            QMessageBox::warning(this, tr("Error"), tr("Key file does not exist."));
            return false;
        }
    }
    return true;
}

inline bool y2yUI::check_output_file(QString& check_outfile)
{
    // 检查输出路径是否存在和文件名是否为空
    if (ui->lineEdit_outPath->text().isEmpty()) {
        QMessageBox::warning(this, tr("Error"), tr("Please select the output path."));
        return false;
    }
    QDir output_dir(ui->lineEdit_outPath->text());
    if (!output_dir.exists()) {
        QMessageBox::warning(this, tr("Error"), tr("Output path does not exist."));
        return false;
    }
    if (ui->lineEdit_outFille->text().isEmpty()) {
        QMessageBox::warning(this, tr("Error"), tr("Please input the output file name."));
        return false;
    }
    // 输入输出文件是否一致
    if (ui->lineEdit_input->text() == check_outfile) {
        QMessageBox::warning(this, tr("Error"), tr("Input file and output file are the same."));
        return false;
    }

    // 检查输出文件是否存在
    QFileInfo check_output_file(check_outfile);
    if (check_output_file.exists()) {
        if (!isAddFile) {
            // 确认是否覆盖
            QMessageBox::StandardButton button = QMessageBox::question(this, tr("Warning"), tr("Output file already exists. Do you want to cover it?"), QMessageBox::Yes | QMessageBox::No, QMessageBox::No);
            if (button == QMessageBox::No) {
                return false;
            }
        }
    }
    return true;
}

void y2yUI::pushButton_add_clicked()
{
    // 设置 pushButton_add 背景色为粉色
    QPalette palette;
    palette.setColor(QPalette::Button, QColor(255, 192, 203));
    ui->pushButton_add->setPalette(palette);
    // 设置 pushButton_cover 背景色为默认颜色
    ui->pushButton_cover->setPalette(defaultPushbuttonColor);

    isAddFile = true;
}

void y2yUI::pushButton_cover_clicked()
{
    // 设置 pushButton_cover 背景色为粉色
    QPalette palette;
    palette.setColor(QPalette::Button, QColor(255, 192, 203));
    ui->pushButton_cover->setPalette(palette);
    // 设置 pushButton_add 背景色为默认颜色
    ui->pushButton_add->setPalette(defaultPushbuttonColor);

    isAddFile = false;
}

void y2yUI::pushButton_textToFile_clicked()
{
    // 检查文本框内容是否为空
    if (ui->textEdit_show->toPlainText().isEmpty()) {
        QMessageBox::warning(this, tr("Error"), tr("Please input the text content."));
        return;
    }

    // 检查输出文件是否存在
    QString output_file = ui->lineEdit_outPath->text() + "/" + ui->lineEdit_outFille->text();
    if (!check_output_file(output_file))
        return;

    // 检查密钥文件
    if (!check_key())
        return;

    // 设置 y2yCtx 密钥
    set_y2yCtx_key();

    // 加密/解密
    y2_codec_mem_to_file(&ctx, output_file.toUtf8().data(), isAddFile ? "a+" : "w+", ui->textEdit_show->toPlainText().toUtf8().data(), ui->textEdit_show->toPlainText().toUtf8().size());
}

void y2yUI::pushButton_show_clicked()
{
    // 检查输入文件
    if (!check_input_file())
        return;

    // 显示输入文件内容
    QFile file(ui->lineEdit_input->text());
    if (!file.open(QIODevice::ReadOnly)) {
        QMessageBox::warning(this, tr("Error"), tr("Failed to open input file. Please check the input file "));
        return;
    }
    QTextStream in(&file);
    // 移动文件指针到指定位置
    in.seek(ui->spinBox_inFileStart->value());
    QString content = in.readAll();
    ui->textEdit_show->clear();
    ui->textEdit_show->setText(content);
    file.close();
}

inline void y2yUI::set_y2yCtx_key() {
    // 设置 y2yCtx 密钥
    if (isFileKey) {
        if (ui->comboBox_key->currentText() == u8"全部")
            y2_load_file_key(&ctx, ui->lineEdit_keyFile->text().toUtf8().data(), 0);
        else
            y2_load_file_key(&ctx, ui->lineEdit_keyFile->text().toUtf8().data(), ui->spinBox_keyLen->value());
    }
    else {
        // 输入密钥，获取密钥数据
        if (ui->lineEdit_keyContent->text().isEmpty()) {
            QMessageBox::warning(this, tr("Error"), tr("Please input the key content."));
            return;
        }
        else if (ui->comboBox_key->currentText() == u8"全部") {
            int key_len = ui->lineEdit_keyContent->text().toUtf8().size();
            y2_set_key_content(&ctx, ui->lineEdit_keyContent->text().toUtf8().data(), key_len);
        }
        else {
            int key_len = ui->spinBox_keyLen->value();
            y2_set_key_content(&ctx, ui->lineEdit_keyContent->text().toUtf8().data(), key_len);
        }
    }
}

void y2yUI::pushButton_showCodec_clicked()
{
    // 检查输入文件
    if (!check_input_file())
        return;

    // 检查密钥文件
    if (!check_key())
        return;
    
    QFile input_file(ui->lineEdit_input->text());
    if (!input_file.open(QIODevice::ReadOnly)) {
        QMessageBox::warning(this, tr("Error"), tr("Failed to open input file. Please check the input file "));
        return;
    }
    //QTextStream in(&input_file);
    QByteArray content;
    content.resize(input_file.size()); // 预留文件大小的内存空间
    input_file.close();
    
    // 设置密钥
    set_y2yCtx_key();

    // 查看 content 的大小
    //qDebug() << "content size: " << content.size();

    // 加密/解密到 content
    y2_codec_file_to_mem(&ctx, content.data(), input_file.size(), ui->lineEdit_input->text().toUtf8().data(), ui->spinBox_inFileStart->value());

    // 设置 textEdit_show 的内容
    ui->textEdit_show->clear();
    ui->textEdit_show->setText(content);
}

void y2yUI::pushButton_fileToFile_clicked()
{
    // 检查输入文件是否存在
    if (!check_input_file())
        return;

    // 拼接输出文件
    QString output_file = ui->lineEdit_outPath->text() + "/" + ui->lineEdit_outFille->text();
    
    // 检查输出路径是否存在和文件名是否为空
    if (!check_output_file(output_file))
        return;

    // 检查密钥文件
    if (!check_key())
        return;

    // 设置 y2yCtx 密钥
    set_y2yCtx_key();

    // 加密/解密
    y2_codec_file_to_file(&ctx, output_file.toUtf8().data(), isAddFile ? "a+" : "w+", ui->lineEdit_input->text().toUtf8().data(), ui->spinBox_inFileStart->value(), 0);
}

void y2yUI::pushButton_clear_clicked()
{
    // 清空输入文件内容
    ui->textEdit_show->clear();
}
